<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Introduction to FreeS/WAN</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
<STYLE TYPE="text/css"><!--
BODY { font-family: serif }
H1 { font-family: sans-serif }
H2 { font-family: sans-serif }
H3 { font-family: sans-serif }
H4 { font-family: sans-serif }
H5 { font-family: sans-serif }
H6 { font-family: sans-serif }
SUB { font-size: smaller }
SUP { font-size: smaller }
PRE { font-family: monospace }
--></STYLE>
</HEAD>
<BODY>
<A HREF="toc.html">Contents</A>
<A HREF="background.html">Previous</A>
<A HREF="makecheck.html">Next</A>
<HR>
<H1><A name="user.examples">FreeS/WAN script examples</A></H1>
 This file is intended to hold a collection of user-written example
 scripts or configuration files for use with FreeS/WAN.
<P> So far it has only one entry.</P>
<H2><A name="poltorak">Poltorak's Firewall script</A></H2>
<PRE>
From: Poltorak Serguei &lt;poltorak@dataforce.net&gt;
Subject: [Users] Using FreeS/WAN
Date: Tue, 16 Oct 2001

Hello.

I'm using FreeS/WAN IPsec for half a year. I learned a lot of things about
it and I think it would be interesting for someone to see the result of my
experiments and usage of FreeS/WAN. If you find a mistake in this
file, please e-mail me. And excuse me for my english... I'm learning.. :)

I'll talk about vary simple configuration:

addresses prefix = 192.168

    lan1          sgw1     .0.0/24 (Internet)       sgw2            lan2
  .1.0/24---[ .1.1 ; .0.1 ]===================[ .0.10 ; . 2.10 ]---.2.0/24


We need to let lan1 see lan2 across Internet like it is behind sgw1. The
same for lan2. And we need to do IPX bridge for Novel Clients and NDS
synchronization.

my config:
------------------- ipsec.conf -------------------
conn lan1-lan2
        type=tunnel
        compress=yes
        #-------------------
        left=192.168.0.1
        leftsubnet=192.168.1.0/24
        #-------------------
        right=192.168.0.10
        rightsubnet=192.168.2.0/24
        #-------------------
        auth=esp
        authby=secret
--------------- end of ipsec.conf ----------------

ping .2.x from .1.y   (y != 1)
It works?? Fine. Let's continue...

Why y != 1 ?? Because kernel of sgw1 have 2 IP addresses and it will choose
the first IP (which is used to go to Internet) .0.1 and the packet won't go
through IPsec tunnel :(  But if do ping on .1.1 kernel will respond from
that address (.1.1) and the packet will be tunneled. The same problem occurred then
.2.x sends a packet to .1.2 which is down at the moment. What happens? .1.1
sends ARP requesting .1.2... after 3 tries it send to .2.x an destunreach,
but from his &quot;natural&quot; IP or .0.1 . So the error message won't be delivered!
It's a big problem...

Resolution... One can manipulate with ipsec0 or ipsec0:0 to solve the
problem (if ipsec0 has .1.1 kernel will send packets correctly), but there
are powerful and elegant iproute2 :) We simply need to change source address
of packet that goes to other secure lan. This is done with

ip route replace 192.168.2.0/24 via 192.168.0.10 dev ipsec0 src 192.168.1.1

Cool!! Now it works!!

The second step. We want install firewall on sgw1 and sgw2. Encryption of 
traffic without security isn't a good idea. I don't use {left|right}firewall, 
because I'm running firewall from init scripts.

We want IPsec data between lan1-lan2, some ICMP errors (destination
unreachable, TTL exceeded, parameter problem and source quench), replying on 
pings from both lans and Internet, ipxtunnel data for IPX and of course SSH
between sgw1 and sgw2 and from/to one specified host.

I'm using ipchains. With iptables there are some changes.

---------------- rc.firewall ---------------------
#!/bin/sh
#
# Firewall for IPsec lan1-lan2
#

IPC=/sbin/ipchains
ANY=0.0.0.0/0

# left
SGW1_EXT=192.168.0.1
SGW1_INT=192.168.1.1
LAN1=192.168.1.0/24

# right
SGW2_EXT=192.168.0.10
SGW2_INT=192.168.2.10
LAN2=192.168.2.0/24

# SSH from and to this host
SSH_PEER_HOST=_SOME_HOST_

# this is for left. exchange these values for right.
MY_EXT=$SGW1_EXT
MY_INT=$SGW1_INT
PEER_EXT=$SGW2_EXT
PEER_INT=$SGW2_INT
INT_IF=eth1
EXT_IF=eth0
IPSEC_IF=ipsec0
MY_LAN=$LAN1
PEER_LAN=$LAN2

$IPC -F
$IPC -P input DENY
$IPC -P forward DENY
$IPC -P output DENY

# Loopback traffic
$IPC -A input -i lo -j ACCEPT
$IPC -A output -i lo -j ACCEPT

# for IPsec SGW1-SGW2
## IKE
$IPC -A input -p udp -s $PEER_EXT 500 -d $MY_EXT 500 -i $EXT_IF -j ACCEPT
$IPC -A output -p udp -s $MY_EXT 500 -d $PEER_EXT 500 -i $EXT_IF -j ACCEPT
## ESP
$IPC -A input -p 50 -s $PEER_EXT -d $MY_EXT -i $EXT_IF -j ACCEPT
### we don't need this line ### $IPC -A output -p 50 -s $MY_EXT -d $PEER_EXT -i $EXT_IF -j ACCEPT
## forward LAN1-LAN2
$IPC -A forward -s $MY_LAN -d $PEER_LAN -i $IPSEC_IF -j ACCEPT
$IPC -A forward -s $PEER_LAN -d $MY_LAN -i $INT_IF -j ACCEPT
$IPC -A output -s $PEER_LAN -d $MY_LAN -i $INT_IF -j ACCEPT
$IPC -A input -s $PEER_LAN -d $MY_LAN -i $IPSEC_IF -j ACCEPT
$IPC -A input -s $MY_LAN -d $PEER_LAN -i $INT_IF -j ACCEPT
$IPC -A output -s $MY_LAN -d $PEER_LAN -i $IPSEC_IF -j ACCEPT

# ICMP
#
## Dest unreachable
### from/to Internet
$IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
### from/to Lan
$IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
### from/to Peer Lan
$IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
#
## Source quench
### from/to Internet
$IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type source-quench -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
### from/to Lan
$IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type source-quench -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
### from/to Peer Lan
$IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type source-quench -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
#
## Parameter problem
### from/to Internet
$IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type parameter-problem -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
### from/to Lan
$IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type parameter-problem -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
### from/to Peer Lan
$IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type parameter-problem -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
#
## Time To Live exceeded
### from/to Internet
$IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type time-exceeded -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
### to Lan
$IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type time-exceeded -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
### to Peer Lan
$IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
$IPC -A output -p icmp --icmp-type time-exceeded -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT

# ICMP PINGs
## from Internet
$IPC -A input -p icmp -s $ANY -d $MY_EXT --icmp-type echo-request  -i $EXT_IF -j ACCEPT
$IPC -A output -p icmp -s $MY_EXT -d $ANY --icmp-type echo-reply  -i $EXT_IF -j ACCEPT
## from LAN
$IPC -A input -p icmp -s $ANY -d $MY_INT --icmp-type echo-request -i $INT_IF -j ACCEPT
$IPC -A output -p icmp -s $MY_INT -d $ANY --icmp-type echo-reply  -i $INT_IF -j ACCEPT
## from Peer LAN
$IPC -A input -p icmp -s $ANY -d $MY_INT --icmp-type echo-request -i $IPSEC_IF -j ACCEPT
$IPC -A output -p icmp -s $MY_INT -d $ANY --icmp-type echo-reply  -i $IPSEC_IF -j ACCEPT

# SSH
## from SSH_PEER_HOST
$IPC -A input -p tcp -s $SSH_PEER_HOST -d $MY_EXT 22 -i $EXT_IF -j ACCEPT
$IPC -A output -p tcp \! -y -s $MY_EXT 22 -d $SSH_PEER_HOST -i $EXT_IF -j ACCEPT
## to SSH_PEER_HOST
$IPC -A input -p tcp \! -y -s $SSH_PEER_HOST 22 -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p tcp -s $MY_EXT -d $SSH_PEER_HOST 22 -i $EXT_IF -j ACCEPT
## from PEER
$IPC -A input -p tcp -s $PEER_EXT -d $MY_EXT 22 -i $EXT_IF -j ACCEPT
$IPC -A output -p tcp \! -y -s $MY_EXT 22 -d $PEER_EXT -i $EXT_IF -j ACCEPT
## to PEER
$IPC -A input -p tcp \! -y -s $PEER_EXT 22 -d $MY_EXT -i $EXT_IF -j ACCEPT
$IPC -A output -p tcp -s $MY_EXT -d $PEER_EXT 22 -i $EXT_IF -j ACCEPT

# ipxtunnel
$IPC -A input -p udp -s $PEER_INT 2005 -d $MY_INT 2005 -i $IPSEC_IF -j ACCEPT
$IPC -A output -p udp -s $MY_INT 2005 -d $PEER_INT 2005 -i $IPSEC_IF -j ACCEPT

---------------- end of rc.firewall ----------------------

To understand this we need to look on this scheme:

           ++-----------------------&lt;----------------------------+
           || ipsec0                                             |
           \/                                                    |
 eth0  +--------+    /---------/ yes  /---------/ yes +-----------------------+
------&gt;| INPUT  |--&gt;/ ?local? /-----&gt;/ ?IPsec? /-----&gt;| decrypt &amp;decapsulate |
 eth1  +--------+  /---------/      /---------/       +-----------------------+
                       || no            || no
                       \/               \/
                  +----------+      +---------+        +-------+
                  | routing  |      |  local  |        | local |
                  | decision |      | deliver |        | send  |
                  +----------+      +---------+        +-------+
                       ||                                 ||
                       \/                                 \/
                   +---------+                       +----------+
                   | forward |                       | routing  |
                   +---------+                       | decision |
                       ||                            +----------+
                       ||                                  ||
                       ++----------------&lt;-----------------++
                       ||
                       \/
                   +--------+ eth0
                   | OUTPUT | eth1
                   +--------+ ipsec0
                       ||
                       \/
                   /---------/ yes +-----------------------+
                  / ?IPsec? /-----&gt;| encrypt &amp;encapsulate |
                 /---------/       +-----------------------+
                      || no                    ||
                      ||                       ||
                      ||                       \/   eth0, eth1
                      ++-----------------------++--------------&gt;

This explain how a packet traverse TCP/IP stack in IPsec capable kernel.

FIX ME, please, if there are any errors

Test the new firewall now.


Now about IPX. I tried 3 programs for tunneling IPX: tipxd, SIB and ipxtunnel

tipxd didn't send packets.. :(
SIB and ipxtunnel worked fine :)
With ipxtunnel there was a little problem. In sources there are an error.

--------------------- in main.c ------------------------
&lt;       bytes += p.len;
---
&gt;       bytes += len;
--------------------------------------------------------

After this FIX everything goes right...

------------------- /etc/ipxtunnel.conf ----------------
port    2005
remote  192.168.101.97    2005
interface eth1
--------------- end of /etc/ipxtunnel.conf -------------

I use IPX tunnel between .1.1 and .2.10 so we don't need to encrypt nor
authenticate encapsulated IPX packets, it is done with IPsec.

If you don't wont to use iproute2 to change source IP you need to use SIB
(it is able to bind local address) or establish tunnel between .0.1 and
.0.10 (external IPs, you need to do encryption in the program, but it isn't
strong).

For now I'm using ipxtunnel.

I think that's all for the moment. If there are any error, please e-mail me: 
poltorak@df.ru . It would be cool if someone puts the scheme of TCP/IP in
kernel and firewall example on FreeS/WAN's manual pages.

PoltoS
</PRE>
<HR>
<A HREF="toc.html">Contents</A>
<A HREF="background.html">Previous</A>
<A HREF="makecheck.html">Next</A>
</BODY>
</HTML>
